﻿//Copyright © Omega Point 2008
//All rights reserved.
//This Software is Licensed under the New BSD License
//for a full copy of this license see http://www.codeplex.com/networkmessenger/license
//Redistributions of source code must retain the above copyright notice.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace NetworkMessenger
{
    public class MessageServer
    {
        private TcpListener server;

        private bool serverRunning;

        /// <summary>
        /// Creates a new server instance with the specified port
        /// </summary>
        /// <param name="Port">Port to listen at</param>
        public MessageServer(int Port)
        {
            server = new TcpListener(IPAddress.Any, Port); 
            serverRunning = false;
        }
       
        /// <summary>
        /// Runs the Current Server
        /// </summary>
        public void RunServer()
        {
            server.Start();
            server.BeginAcceptTcpClient(new AsyncCallback(doAcceptTcpClientCallback), server);
            serverRunning = true;
        }

        /// <summary>
        /// Stops the server if Running
        /// </summary>
        public void StopServer()
        {
            serverRunning = false;
            server.Stop();
        }

        /// <summary>
        /// Gets the current status of the server
        /// </summary>
        public bool IsRunning
        {
            get { return serverRunning; }
        }

        private void doAcceptTcpClientCallback(IAsyncResult ar)
        {
            try
            {
                TcpListener listener = (TcpListener)ar.AsyncState;

                TcpClient client = listener.EndAcceptTcpClient(ar);
                EndPoint ep = client.Client.RemoteEndPoint;
                OnMessage(new MessageEventArgs(Message.FromStream(client.GetStream()),ep));

                client.Close();

                listener = null;
                client = null;
            }
            catch (Exception)
            {
                //Ignore any Exceptions and continue
            }
            finally
            {
                try
                {
                    //Listen for next message
                    server.BeginAcceptTcpClient(new AsyncCallback(doAcceptTcpClientCallback), server);  
                }
                catch (InvalidOperationException)
                {
                    //Ignore as Server has Shut Down
                }
                       
            }

        }
        
        /// <summary>
        /// Raised when a new message is Received
        /// </summary>
        public event MessageEventHandler OnNewMessage;

        protected virtual void OnMessage(MessageEventArgs e)
        {
            MessageEventHandler handler = OnNewMessage;
            if (handler != null)
            {
                // Invokes the delegates. 
                handler(this, e);
            }
        }

    }

    public delegate void MessageEventHandler(object sender, MessageEventArgs e);

    /// <summary>
    /// Arguments for a Message Event
    /// </summary>
    public class MessageEventArgs : EventArgs
    {
        private Message msg;
        private EndPoint endPoint;

        /// <summary>
        /// New MessageEventArgs containing only the message
        /// </summary>
        /// <param name="message">Message Received</param>
        public MessageEventArgs(Message message)
        {
            msg = message;
            endPoint = null;
        }

        public MessageEventArgs(Message message, EndPoint fromEndPoint)
        {
            msg = message;
            endPoint = fromEndPoint;
        }

        public Message MessageReceived
        {
            get { return msg; }
        }
        public EndPoint RemoteEndPoint
        {
            get { return endPoint; }
        }
    }
}
